# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------

import logging
from .corelibs import (chkparsdaemon)
from .importapps import (DFEATURES,FTARGETS)
from .servers import (SetupDaemons)

logger = logging.getLogger()


def paramfeature(feature,param):
    if feature == 'EVT2NETQ':
        if param in SetupDaemons:
            return SetupDaemons[param].evtnetq
    return param


def chkdfeature(params):
    # params = [name:ctrl,decname,feature(dargs)]
    if len(params) != 3:
        logger.error('Three parameters needed for decoded feature')
        return None
    p0 = chkparsdaemon(params[0],SetupDaemons)
    if not p0:
        logger.error('Syntax error for decoded feature')
        return None
    dev,name,ctrl = p0
    decname = params[1]
    if decname not in dev.decodernames:
        logger.error('Decoder %s not yet setup for controller %s',decname,name)
        return None
    p1 = params[2].split('(')
    if len(p1) == 0:
        logger.error('Syntax error for decoded feature')
        return None
    feature= p1[0]
    if feature not in DFEATURES:
        logger.error('Unknown decoded feature (syntax error) %s',feature)
        return None
    ftargets = []
    if len(p1) == 1: 
        dargs = None
    elif '[' in p1[1]:
        lp1 = p1[1].split(']')
        for t in lp1[0].strip('[').split(','):
            if t in FTARGETS:
                ftargets.append(FTARGETS[t]())
        dargs = lp1[1].strip(')').lstrip(',')
    else:
        dargs = p1[1].strip(')')
    return dev,name,ctrl,feature,dargs,ftargets


def adddfeature(params):
    """
    Add decoded feature for controller
    params = [name:ctrl,decname,feature(ftargets,dargs)]
    """
    p = chkdfeature(params)
    if not p:
        return False
    dev,name,ctrl,feature,dargs,ftargets = p
    decname = params[1]
    lnamedf = decname + '-FEATURES'
    i = dev.dfeaturenames.index(lnamedf)
    ldfn,ldfr = dev.dfeatures[i]
    if feature in ldfn:
        logger.error('Decoded feature has been already added %s',feature)
        return False
    ldfn.append(feature)
    args = []
    if len(ftargets) != 0 : args += [ftargets]
    #if dargs: args += dargs.split(',')
    if dargs:
        for a in dargs.split(','):
            args.append(paramfeature(feature,a))
    try:
        if len(args) != 0:
            ldfr.append(DFEATURES[feature](*args))
        else:
            ldfr.append(DFEATURES[feature]())
        logger.warning('Decoded feature %s has been successfully added to %s',feature,params[0])
    except Exception as e:
        logger.error("%s : %s", repr(e.__class__), str(e))
        logger.error("In adding decoded feature %s to decoder %s" ,feature,decname)
        return False
    return True


def rmdfeature(params):
    """
    Remove FEATURE from controller feature list
    """
    p = chkdfeature(params)
    if not p:
        return False
    dev,name,ctrl,feature,dargs,ftargets = p
    decname = params[1]
    lnamedf = decname + '-FEATURES'
    i = dev.dfeaturenames.index(lnamedf)
    ldfn,ldfr = dev.dfeatures[i]
    if feature not in ldfn:
        logger.error('Feature not yet added %s',feature)
        return False
    i = ldfn.index(feature)
    ldfr[i].close()		#Close coroutine generator
    ldfr.pop(i)
    ldfn.remove(feature)
    logger.info("Feature %s removed for controller %s",feature,ctrl)
    return True


def chkd2md(params):
    # params = [name:MEVTQ,feature(dargs)]
    p0 = chkparsdaemon(params[0],SetupDaemons)
    if not p0:
        logger.error('Syntax error for parameters')
        return None
    dev,name,ctrl = p0
    p1 = params[1].split('(')
    if len(p1) == 0:
        logger.error('Syntax error for decoded feature')
        return None
    feature= p1[0]
    if feature not in DFEATURES:
        logger.error('Unknown decoded feature (syntax error) %s',feature)
        return None
    ftargets = []
    if len(p1) == 1: 
        dargs = None
    elif '[' in p1[1]:
        lp1 = p1[1].split(']')
        for t in lp1[0].strip('[').split(','):
            if t in FTARGETS:
                ftargets.append(FTARGETS[t]())
        dargs = lp1[1].strip(')').lstrip(',')
    else:
        dargs = p1[1].strip(')')
    return dev,feature,dargs,ftargets


def add2md(params,mevtq):
    """
    Add decoded feature to multievtq
    params = [name:MEVTQ,feature(ftargets,dargs)]
    """
    p = chkd2md(params)
    if not p:
        return False
    dev,feature,dargs,ftargets = p
    dev = mevtq
    if feature in dev.dfeaturenames:
        logger.error('Decoded feature has been already added %s',feature)
        return False
    args = []
    if len(ftargets) != 0 : args += [ftargets]
    if dargs: args += dargs.split(',')
    try:
        if len(args) != 0:
            dev.dfeatures.append(DFEATURES[feature](*args))
        else:
            dev.dfeatures.append(DFEATURES[feature]())
        logger.warning('Decoded feature %s has been successfully added to %s',repr(dev.dfeatures),repr(dev))
    except Exception as e:
        logger.error("%s : %s", repr(e.__class__), str(e))
        logger.error("In adding decoded feature %s to MEVTQ" ,feature)
        return False
    return True
